import apiCode from "@/constants/ApiCode";
import pinia from "@/store/index.js";
import token from "@/store/token.js";
import axios from "axios";
import { MD5, lib } from "crypto-js";

const tokenStore = token(pinia);

const baseURL = import.meta.env.VITE_APP_FILE_API;

const req = axios.create({
  baseURL: baseURL,
  timeout: 60000,
});

req.interceptors.request.use(
  (config) => {
    let tokenStr = tokenStore.getValidToken();
    if (tokenStr.length > 0) {
      config.headers["W-Token"] = tokenStr;
    }
    return config;
  },
  (error) => {
    console.warn("req error:", error);
    return Promise.reject(error);
  }
);

req.interceptors.response.use(
  (response) => {
    if (response.status != apiCode.OK) {
      return Promise.reject(new Error(response.statusText || "Error"));
    }
    return response.data;
  },
  (error) => {
    console.log("req response error:" + error);
  }
);

/**
 * 对文件进行分片
 * @param {File} file
 */
function chunkFile(file) {
  // 每片的大小
  let chunkSize = 1 * 1024 * 1024;
  // let chunkSize = 512 * 1024;

  let cnt = Math.ceil(file.size / chunkSize);
  let list = {
    length: cnt,
  };
  let pList = [];

  for (let i = 0; i < cnt; i++) {
    pList.push(
      new Promise((resolve, reject) => {
        let tmp = "";
        let start = i * chunkSize;
        let end = Math.min(file.size, start + chunkSize);

        // 切割文件
        tmp = file.slice(start, end);
        // list[i] = {
        //     content : tmp,
        //     md5 : MD5(tmp).toString()
        // };
        // resolve()
        let reader = new FileReader();
        reader.onload = function (ev) {
          // 每个片里面装的是 base64编码后的内容
          // 去掉 base64,前面的的内容
          let p = ev.target.result;
          list[i] = {
            content: tmp,
            md5: MD5(lib.WordArray.create(p)).toString(),
          };
          resolve();
        };
        reader.onerror = function (er) {
          reject(er);
        };
        // reader.readAsDataURL(tmp)
        reader.readAsArrayBuffer(tmp);
      })
    );
  }

  return new Promise((res, rej) => {
    Promise.all(pList)
      .then(() => {
        res(list);
      })
      .catch((err) => {
        rej(err);
      });
  });
}

const fileApi = {
  baseURL: baseURL,

  uploadOneURL: baseURL + "/file/upload/one",

  // 上传
  uploadOne: (file) => {
    return req.post(fileApi.uploadOneURL, {
      file,
    });
  },

  /**
   *
   * @param {File} file
   */
  chunkUpload: (file) => {
    return new Promise((resolve, reject) => {
      //

      fileApi
        .chunkUploadStep1(file)
        .then((res) => {
          if (res.code != apiCode.OK) {
            reject(new Error(res.msg));
            return;
          }
          let uk = res.data.uk;

          chunkFile(file)
            .then((chunkList) => {
              let promiseList = [];
              for (let i = 0; i < chunkList.length; i++) {
                promiseList.push(
                  new Promise((resolve2, reject2) => {
                    const formData = new FormData();
                    formData.append("file", chunkList[i].content);
                    formData.append("uk", uk);
                    formData.append("total", chunkList.length);
                    formData.append("idx", i + 1);
                    formData.append("md5", chunkList[i].md5);

                    // fileApi.chunkUploadStep2({
                    //     uk: uk,//'第一步返回的 uk',
                    //     total: chunkList.length, // '总切片数量，如：2',
                    //     idx: i + 1, //'当前索引，从1开始,如：2',
                    //     file : chunkList[i].content,
                    //     // type : 'file', // file：formData 形式上传文件， base64 上传base64的内容
                    //     // content: chunkList[i].content, // 当前分片的base64内容
                    //     md5 : chunkList[i].md5, // md5校验
                    // })

                    fileApi.chunkUploadStep2(formData).then((step2Res) => {
                      if (step2Res.code == apiCode.OK) {
                        resolve2(step2Res.data);
                      } else {
                        reject2(new Error(step2Res.msg));
                      }
                    });
                  })
                );
              }

              // 上传所有分片
              Promise.all(promiseList)
                .then((resList) => {
                  // 上传的结果里面只会有一个请求返回成功

                  let resData = null;
                  resList.forEach((item) => {
                    if (item.url !== undefined) {
                      resData = item;
                    }
                  });

                  if (resData === null) {
                    reject(new Error("返回数据有误"));
                  } else {
                    resolve(resData);
                  }
                })
                .catch((err) => {
                  reject(err);
                });
            })
            .catch((er) => {
              reject(er);
            });
        })
        .catch((er) => {
          reject(er);
        });
    });
  },

  /**
   * 上传的第一步
   * @param {File} file
   */
  chunkUploadStep1: (file) => {
    return req.post("/file/upload/chunkReady", {
      filename: file.name,
    });
  },

  /**
   * 上传的第2步
   * @param {Object} data
   */
  chunkUploadStep2: (data) => {
    return req.post("/file/upload/chunk", data);
  },
};

export default fileApi;
